<?php
/**
 * [ Random Framework ]
 *
 * @version 2.0.0 (build 20130520)
 *
 * @link http://0x00.sinaapp.com/random.html
 * 
 * @author Coseylee (Coseylee@gmail.com).
 *
 */

/**
 * MongoDB 数据库操作类
 */
class mongo_db extends random_database
{
	private $connect; // Mongo 连接
	private $results; // 上一次结果集
	private $lastID; // 最后插入记录的ID
	private $affectedRows; // 操作影响行数
	private static $count = 0; // 查询次数
	private static $sqls = array(); // 查询语句与时间
	
	/**
	 * 连接数据库
	 * 
	 * @param array $db_config 参数
	 */
	function __construct($db_config)
	{
		if (class_exists('mongo') === false)
		{
			throw new random_exception('Dont Support MongoDB Database');
		}
		
		$auth = $db_config['user'] !== '' ? $db_config['user'].':'.$db_config['pass'].'@' : '';
		
		try
		{
			$this -> connect = array();
			$this -> connect['link'] = new Mongo('mongodb://'.$auth.$db_config['host'].':'.$db_config['port'].'/'.$db_config['name']);
			$this -> connect['dbname'] = $db_config['name'];
		}
		catch (Exception $e)
		{
			throw new random_exception('Can\'t Connect MongoDB Server');
		}
	}
	
	/**
	 * 获取 MongoDB 版本
	 * 
	 */
	function getVersion()
	{
		return Mongo::VERSION;
	}
	
	/**
	 * 插入操作
	 * 
	 * @param $table 表名
	 * @param $data 数组形式的插入数据
	 * @param $replace 是否替换插入
	 */
	function insert($table, $data, $replace = false)
	{
		$option = array();
		$option['operate'] = 'insert';
		$option['table'] = $table;
		$option['data'] = $data;
		return $option;
	}
	
	/**
	 * 查询
	 * 
	 * @param $table 表名
	 * @param $where 查询条件 array('username' => 'admin', 'uid' => 1)
	 * @param $order 排序条件 array('id' => -1, 'date' => 1)
	 * @param $limit 限制 array('skip', 'limit')
	 * @param $data 查询字段 array('username', 'password', 'age')
	 */
	function select($table, $where = '', $order = '', $limit = '', $data = '*')
	{
		$option = array();
		$option['operate'] = 'select';
		$option['table'] = $table;
		$option['where'] = $where;
		$option['order'] = $order;
		$option['limit'] = $limit;
		$option['data'] = $data;
		return $option;
	}
	
	/**
	 * 查询一条记录
	 * 
	 * @param $table 表名
	 * @param $where 查询条件 array('username' => 'admin', 'uid' => 1)
	 * @param $order 排序条件 array('id' => -1, 'date' => 1)
	 * @param $data 查询字段 array('username', 'password', 'age')
	 */
	function select_one($table, $where = '', $order = '', $data = '*')
	{
		return $this -> select($table, $where, $order, '1', $data);
	}
	
	/**
	 * 更新操作
	 * 
	 * @param $table 表名
	 * @param $data 数组形式的数据
	 * @param $where 条件（数组或字符串）
	 */
	function update($table, $data, $where)
	{
		$option = array();
		$option['operate'] = 'update';
		$option['table'] = $table;
		$option['data'] = $data;
		$option['where'] = $where;
		return $option;
	}
	
	/**
	 * 删除操作
	 * 
	 * @param $table 表名
	 * @param $where 条件 array('username' => 'admin', 'uid' => 1)
	 */
	function delete($table, $where)
	{
		$option = array();
		$option['operate'] = 'delete';
		$option['table'] = $table;
		$option['where'] = $where;
		return $option;
	}
	
	/**
	 * 执行操作
	 * 
	 * @param $optioin 操作配置信息
	 */
	function query($option)
	{
		extract($option); // 这里已打散变量，下面使用请注意。
		unset($option);
		$return = null;
		
		$debug = array($operate.' => '.$this -> connect['dbname'], microtime(true));
		
		$collection = $this -> connect['link'] -> selectCollection($this -> connect['dbname'], $table);
		
		$this -> lastID = $this -> affectedRows = 0;
		
		switch ($operate)
		{
			case 'insert':
			{
				// 应当返回ID
				try
				{
					$return = $collection -> insert($data, array('safe' => true));
					if ($return['ok'] == true)
					{
						$return = $this -> lastID = $data['_id'];
					}
					else
					{
						$return = false;
					}
				}
				catch (Exception $e)
				{
					$return = false;
				}
			}
			break;
			case 'select':
			{
				if ($where === '') $where = array();
				if ($data === '*') $data = array();

				if ($limit === '1')
				{
					$limit = array(0, 1);
				}
				
				$string = "\$this -> results = \$collection -> find(\$where, \$data)";
				
				if (is_array($order) && !empty($order))
				{
					$string .= ' -> sort($order)';
				}
				
				if (is_array($limit) && !empty($limit))
				{
					$string .= ' -> skip($limit[0]) -> limit($limit[1])';
				}
				
				try
				{
					// 往往最主要的东西都是那么的不起眼儿。
					eval($string.';');
					
					// 锁定游标
					if (!is_array($order) || empty($order))
					{
						$this -> results -> snapshot();
					}
					
					$return = $this -> num_rows($this -> results) < 1 ? false : $this -> results;
				}
				catch (Exception $e)
				{
					$return = false;
				}
			}
			break;
			case 'update':
			{
				try
				{
					$return = $collection -> update($where, $data, array('safe' => true));
					if ($return['ok'] == true)
					{
						// 影响行数
						$return = $this -> affectedRows = $return['n'];
					}
					else
					{
						//$return = false;
					}
				}
				catch (Exception $e)
				{
					//$return = false;
				}
			}
			break;
			case 'delete':
			{
				if (empty($where))
				{
					$return = false;
					break;
				}
				
				try
				{
					$return = $collection -> remove($where, array('safe' => true));
					if ($return['ok'] == true)
					{
						// 影响行数
						$return = $this -> affectedRows = $return['n'];
					}
					else
					{
						$return = false;
					}
				}
				catch (Exception $e)
				{
					$return = false;
				}
			}
			default:
			return $return;
		}
		
		$debug[1] = sprintf('%.6f', microtime(true) - $debug[1]);
		++self::$count && self::$sqls[] = $debug;
		unset($debug);
		return $return;
	}
	
	/**
	 * 返回一行带关联数组的结果集
	 * 
	 * @param $results 结果集
	 */
	function fetch_array($results)
	{
		if (($results instanceof MongoCursor) && $results -> hasNext())
		{
			return $results -> getNext();
		}
		else
		{
			return false;
		}
	}
	
	/**
	 * 返回一行索引的结果集（Mongo 无效）
	 * 
	 * @param $results 结果集
	 */
	public function fetch_row($results)
	{
		return $this -> fetch_array($results);
	}
	
	/**
	 * 快速获取下一条记录 （格式化结果集后无效）
	 * 
	 */
	function fetch_next()
	{
		return $this -> fetch_array($this -> results);
	}
	
	/**
	 * 开始事务
	 * 
	 */
	function start()
	{
		return false;
	}
	
	/**
	 * 事务提交
	 * 
	 */
	function commit()
	{
		return false;
	}
	
	/**
	 * 事务回滚
	 * 
	 */
	function rollback()
	{
		return false;
	}
	
	/**
	 * 释放结果集
	 * 
	 */
	function free_result()
	{
		$this -> results = null;
		return true;
	}
	
	/**
	 * 返回结果集行数
	 * 
	 * @param $results 结果集
	 */
	function num_rows($results)
	{
		$results = $results == null ? $this -> results : $results;
		return $results -> count(true);
	}
	
	/**
	 * 返回影响行数
	 * 
	 */
	function affected_rows()
	{
		return $this -> affectedRows;
	}
	
	/**
	 * 最后插入的ID
	 * 
	 */
	function insert_id()
	{
		return $this -> lastID;
	}
	
	/**
	 * 返回查询次数
	 * 
	 */
	function query_count()
	{
		return self::$count;
	}
	
	/**
	 * 返回所有查询语句
	 * 
	 */
	function sqls()
	{
		return self::$sqls;
	}
	
	/**
	 * 关闭连接
	 * 
	 */
	function close()
	{
		if($this -> connect['link'] == true) $this -> connect['link'] -> close();
	}
}